import Taro, { nextTick } from "@tarojs/taro";
import { useRequest } from "ahooks";
import { isFunction } from "@tarojs/shared";
import { isPlainObject, isString } from "lodash-es";

import request from "@/utils/request";

type Options<TData, TParams extends any[]> = Parameters<
  typeof useRequest<TData, TParams>
>[1];

export type UseFetchUrl<TParams> = string | ((params: TParams) => string);

export type UseFetchOptions<TData, TParams extends any[]> = {
  // 是否要求token（某些接口不需要token，避免被验证拦截）
  tokenAuth?: boolean;
  // 是否展示默认的加载loading
  showLoading?: boolean;
  // 是否展示默认错误Toast
  showErrorToast?: boolean;

  // 与onBefore相反，返回结果之后，先处理一次数据
  onAfter?: (res: TData) => any;
  formartParams?: (...params: TParams) => any[];
} & Options<TData, TParams>;

const onAfterDefault = (e) => e;

export default <TData = unknown, TParams extends any[] = any[]>(
  fetchUrl: UseFetchUrl<TParams>,
  method?: "GET" | "POST" | "PUT" | UseFetchOptions<TData, TParams>,
  options?: UseFetchOptions<TData, TParams>
) => {
  options =
    options ??
    ((isPlainObject(method) ? method : {}) as UseFetchOptions<TData, TParams>);

  const {
    tokenAuth,
    showLoading,
    showErrorToast,

    onError,
    onAfter = onAfterDefault,
    formartParams,

    ...rest
  } = options;

  const fetchFn = (...params: TParams) => {
    if (showLoading) Taro.showLoading({ title: "正在加载" });

    const getFetchUrl = () =>
      isFunction(fetchUrl) ? fetchUrl(params as TParams) : fetchUrl;

    return request(
      {
        url: getFetchUrl(),
        data: Object.assign(
          {},
          ...(isFunction(formartParams) ? formartParams(...params) : params)
        ),
        method: (method && (isString(method) ? method : "GET")) as
          | "POST"
          | "GET",
      },
      { tokenAuth, showErrorToast }
    )
      .then(onAfter)
      .then((res) => {
        console.log("关闭loading");
        showLoading && nextTick(() => Taro.hideLoading());
        return res;
      })
      .finally(() => {}) as Promise<TData>;
  };

  const res = useRequest<TData, TParams>(fetchFn, {
    ...rest,
    // onError(err, params) {
    //   onError?.(err, params);
    // },
  });

  return res;
};
